﻿namespace SimpleWebServices.Web.Routing
{
    using System;
    using System.Collections.Generic;
    using System.Web.Mvc;
    using System.Web.Routing;
    using SimpleWebServices.Web.Mvc;

    public static class RouteCollectionExtensionMethods
    {
        public static void Register<T>(this RouteCollection routes)
            where T : IRegisterRoutes
        {
            (Activator.CreateInstance(typeof(T)) as IRegisterRoutes).Register(routes);
        }

        public static void Register(this RouteCollection routes, IEnumerable<Type> types)
        {
            if (null == types)
            {
                throw new ArgumentNullException("types");
            }

            foreach (var type in types)
            {
                routes.Register(type);
            }
        }

        public static void Register(this RouteCollection routes, Type type)
        {
            routes.Register(type, false);
        }

        public static void Register(this RouteCollection routes, Type type, bool skipInterface)
        {
            if (null == type)
            {
                throw new ArgumentNullException("type");
            }

            if (type.IsClass && type.IsSubclassOf(typeof(Controller)))
            {
                if (!skipInterface && null != type.GetInterface("IRegisterRoutes"))
                {
                    (Activator.CreateInstance(type) as IRegisterRoutes).Register(routes);
                }

                foreach (var method in type.GetMethods())
                {
                    foreach (object attribute in method.GetCustomAttributes(typeof(RoutingAttribute), true))
                    {
                        (attribute as RoutingAttribute).Register(routes, type, method);
                    }
                }

                foreach (object attribute in type.GetCustomAttributes(typeof(ResourceAttribute), true))
                {
                    routes.Register(type, attribute as ResourceAttribute);
                }
            }
        }

        public static void Register(this RouteCollection routes, Type type, ResourceAttribute resource)
        {
            if (null == type)
            {
                throw new ArgumentNullException("type");
            }
            else if (null == resource)
            {
                throw new ArgumentNullException("resource");
            }

            foreach (var method in type.GetMethods())
            {
                foreach (object attribute in method.GetCustomAttributes(typeof(ContentNegotiationAttribute), true))
                {
                    resource.RegisterRepresentation(routes, type, method, attribute as ContentNegotiationAttribute);
                }

                foreach (object attribute in method.GetCustomAttributes(typeof(PostAttribute), true))
                {
                    resource.RegisterPost(routes, type, method);
                }

                foreach (object attribute in method.GetCustomAttributes(typeof(PutAttribute), true))
                {
                    resource.RegisterPut(routes, type, method);
                }
            }

            resource.RegisterContentNegotiation(routes, type);
            resource.RegisterLanguageNegotiation(routes, type);
        }
    }
}